#include <signal.h>
#include <unistd.h>

#include <cstring>
#include <ctime>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char* argv[]) {
    if (argc > 1 && string(argv[1]) == "--help") {
        cout << argv[0] << " [delay-secs]" << endl;
        return 1;
    }

    cout << argv[0] << ": PID is " << getpid() << endl;

    // Block all signals (except SIGKILL and SIGSTOP)
    sigset_t allSigs;
    sigfillset(&allSigs);
    if (sigprocmask(SIG_SETMASK, &allSigs, nullptr) == -1) {
        perror("sigprocmask");
        return 1;
    }
    cout << argv[0] << ": signals blocked" << endl;

    // Delay so that signals can be sent to us
    if (argc > 1) {
        cout << argv[0] << ": about to delay " << argv[1] << " seconds" << endl;
        sleep(stoi(argv[1]));
        cout << argv[0] << ": finished delay" << endl;
    }

    // Fetch signals until SIGINT or SIGTERM
    siginfo_t si;
    for (;;) {
        auto sig = sigwaitinfo(&allSigs, &si);
        if (sig == -1) {
            perror("sigwaitinfo");
            return 1;
        }

        cout << "got signal: " << sig << " (" << strsignal(sig) << ")" << endl;
        if (sig == SIGINT || sig == SIGTERM) {
            return 0;
        }

        cout << "    si_signo=" << si.si_signo << ", si_code=" << si.si_code
             << " ("
             << ((si.si_code == SI_USER)
                     ? "SI_USER"
                     : (si.si_code == SI_QUEUE) ? "SI_QUEUE" : "other")
             << ")"
             << ", si_value=" << si.si_value.sival_int << endl;
        cout << "    si_pid=" << si.si_pid << ", si_uid=" << si.si_uid << endl;
    }
}
